#include "ImaDbInterface.h"
#include "ImaGlobals.h"
#include "ImaConstants.h"
#include "string.h"

ImaDbInterface* ImaDbInterface::mpDbInterface = NULL;

ImaDbInterface* ImaDbInterface::getInstance(ImaConf& conf) {
	if(mpDbInterface == NULL) {
		LOG(debug, __FILE__, __LINE__, "creating DB interface object");
		mpDbInterface = new ImaDbInterface(conf);
		if( 0 != mpDbInterface->connectToDb()) {
			delete mpDbInterface;
			mpDbInterface = NULL;
		}
	}
	return mpDbInterface;
}

ImaDbInterface::ImaDbInterface(ImaConf& conf): mpConn(NULL) {
	LOG(debug, __FILE__, __LINE__, "ImaDbInterface::ImaDbInterface() called");

	strcpy(mDbHostname, conf.mDbHostname);
	mDbPort = conf.mDbPort;
	strcpy(mDbName, conf.mDbName);
	strcpy(mDbUsername, conf.mDbUsername);
	strcpy(mDbPassword, conf.mDbPassword);
}

ImaDbInterface::~ImaDbInterface() {
	LOG(debug, __FILE__, __LINE__, "ImaDbInterface::~ImaDbInterface() called");

	if(mpConn != NULL) {
		PQfinish(mpConn);
		mpConn = NULL;
	}
}

int ImaDbInterface::connectToDb() {
	LOG(debug, __FILE__, __LINE__, "ImaDbInterface::connectToDb() called");

	char dbConnString[1024];
	sprintf(dbConnString, "hostaddr = '%s' port = '%d' dbname = '%s' \
				user = '%s' password = '%s' connect_timeout = '%d'",
				mDbHostname, mDbPort, mDbName, mDbUsername, mDbPassword, IMA_DB_CONN_TIMEOUT);
	int retVal = -1;

	for(int i = 0; i < IMA_NUM_DB_CONN_RETRIES; i++) {
		mpConn = PQconnectdb(dbConnString);
		if(PQstatus(mpConn) != CONNECTION_OK) {
			char log_msg[1024];
			sprintf(log_msg, "Failed to connect to DB in %d attempt(s); DB conn string: %s ; Error message: %s", i, dbConnString, PQerrorMessage(mpConn));
			LOG(error, __FILE__, __LINE__, log_msg);
		} else {
			char log_msg[1024];
			sprintf(log_msg, "Connection to DB successful in %d attempt(s); DB conn string: %s", i, dbConnString);
			LOG(info, __FILE__, __LINE__, log_msg);
			retVal = 0;
			break;
		}
	}

	return retVal;
}



int ImaDbInterface::getListOfInfoToSend(std::vector<ImaInfo*>& infoVector) {
	char log_msg[1024];
	sprintf(log_msg, "ImaDbInterface::getListOfInfoToSend called");
	LOG(debug, __FILE__, __LINE__, log_msg);

	int retVal = 0;
	char query_string[1024];
	sprintf(query_string, "select info_id, owner_email_id, info from tbl_info, tbl_user where tbl_info.owner_email_id=tbl_user.email_id and (CURRENT_TIMESTAMP - tbl_user.dola) > tbl_info.ttl");

	PGresult* pRes = NULL;
	pRes = PQexec(mpConn, query_string);
	
	if(PQresultStatus(pRes) == PGRES_TUPLES_OK){
		int numRows = PQntuples(pRes);
		for(int i = 0; i < numRows; i++) {
			ImaInfo* pInfo= new ImaInfo;
			pInfo->mInfoId = atol(PQgetvalue(pRes, i, 0));
			strcpy(pInfo->mEmailId, PQgetvalue(pRes, i, 1));
			pInfo->mStrInfo  = std::string(PQgetvalue(pRes, i, 2));

			infoVector.push_back(pInfo);
		}

		sprintf(log_msg, "No. of rows fetched: %d", numRows);
		retVal = 1;
	} else {
		char log_msg[512];
		sprintf(log_msg, "Failed to fetch the list of info, Error: %s", PQresultErrorMessage(pRes));
		LOG(error, __FILE__, __LINE__, log_msg);
		retVal = 0;
	}
	//TODO: also handle database error
	PQclear(pRes);

	return retVal;
}

int ImaDbInterface::getListOfRecipients(const unsigned long infoId, std::vector<ImaRecipient*>& recipientVector) {
	char log_msg[1024];
	sprintf(log_msg, "ImaDbInterface::getListOfRecipients called with info id: %lu", infoId);
	LOG(debug, __FILE__, __LINE__, log_msg);

	int retVal = 0;
	char query_string[1024];
	//sprintf(query_string, "select recipient_id, recipient_name, recipient_email_id, recipient_address, recipient_phone from tbl_recipient where recipient_id in (select recipient_id from tbl_info_recipient where notification_sent='FALSE')");
	sprintf(query_string, "select tbl_recipient.recipient_id, recipient_name, recipient_email_id, recipient_address, recipient_phone_num from tbl_recipient, tbl_info_recipient where tbl_recipient.recipient_id=tbl_info_recipient.recipient_id and info_id='%lu' and notification_sent='FALSE'", infoId);

	PGresult* pRes = NULL;
	pRes = PQexec(mpConn, query_string);
	
	if(PQresultStatus(pRes) == PGRES_TUPLES_OK){
		int numRows = PQntuples(pRes);
		for(int i = 0; i < numRows; i++) {
			ImaRecipient* pRecipient = new ImaRecipient;
			pRecipient->mRecipientId = atol(PQgetvalue(pRes, i, 0));
			strcpy(pRecipient->mRecipientName, PQgetvalue(pRes, i, 1));
			strcpy(pRecipient->mRecipientEmailId, PQgetvalue(pRes, i, 2));
			strcpy(pRecipient->mRecipientAddress, PQgetvalue(pRes, i, 3));
			strcpy(pRecipient->mRecipientPhone, PQgetvalue(pRes, i, 4));

			recipientVector.push_back(pRecipient);
		}

		sprintf(log_msg, "No. of rows fetched: %d", numRows);
		retVal = 1;
	} else {
		char log_msg[512];
		sprintf(log_msg, "Failed to fetch the list of recipients, Error: %s", PQresultErrorMessage(pRes));
		LOG(error, __FILE__, __LINE__, log_msg);
		retVal = 0;
	}
	//TODO: also handle database error
	PQclear(pRes);

	return retVal;

}

